#include "pub_sub.h"


//虚拟头结点，不存储数据
static Publisher_message_t pub_head = 
{
    .topic = "Head",
    .first_sub = NULL,
    .next_pub = NULL
} ;

Subscriber_message_t* subscriber_init(char* topic, uint8_t data_len)
{
    Publisher_message_t* pub = publisher_init(topic, data_len);
    Subscriber_message_t* sub = (Subscriber_message_t*)malloc(sizeof(Subscriber_message_t));
    memset(sub, 0, sizeof(Subscriber_message_t));
    sub -> data_len = data_len;
    for(size_t i = 0; i < QUEUE_SIZE; i++)
    {
        sub -> queue[i] = (void*)malloc(data_len);
    }
    if(pub -> first_sub == NULL)
    {
        pub -> first_sub = sub;
        return sub;
    }

    Subscriber_message_t* temp_sub = pub -> first_sub;
    while(temp_sub -> next_sub)
    {
        temp_sub = temp_sub -> next_sub;
    }
    temp_sub -> next_sub = sub;
    return sub;
}

Publisher_message_t* publisher_init(char* topic, uint8_t data_len)
{
    Publisher_message_t* pub = &pub_head;
    while(pub -> next_pub)
    {
        pub = pub -> next_pub;
        if(strcmp(pub -> topic, topic) == 0)
        {
            pub -> pub_init_flag = 1;
            return pub;            
        }
    }
    Publisher_message_t* new_pub = (Publisher_message_t*)malloc(sizeof(Publisher_message_t));
    new_pub -> next_pub = pub -> next_pub;
    pub -> next_pub = new_pub;
    memset(new_pub, 0, sizeof(Publisher_message_t));
    new_pub -> data_len = data_len;
    strcpy(new_pub -> topic, topic);
    new_pub -> pub_init_flag = 1;
    return new_pub;
}

//这些要加锁吗？？
uint8_t PubPushMessage(Publisher_message_t* pub, void* data)
{
    Subscriber_message_t* sub = pub -> first_sub;
    while(sub)
    {
        if(sub -> size == QUEUE_SIZE)
        {
            sub -> head = (sub -> head + 1) % QUEUE_SIZE;
            sub -> size --;
        }
        memcpy(sub -> queue[sub -> tail], data, sub -> data_len);
        sub -> tail = (sub -> tail + 1) % QUEUE_SIZE;
        sub -> size ++;

        sub = sub -> next_sub;
    }
    return 1;
}

uint8_t SubGetMessage(Subscriber_message_t* sub, void* data)
{
    if(sub -> size == 0)
    {
        return 0;
    }
    memcpy(data, sub -> queue[sub -> head], sub -> data_len);
    sub -> head = (sub -> head + 1) % QUEUE_SIZE;
    sub -> size --;
    return 1;
}
